/**
 * Copyright (C) 2012-2013 jumei, Inc.
 * RpcS.java
 * 2015年6月26日
 */
package org.goface.rpc.io;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;

import org.goface.rpc.Message;
import org.goface.rpc.MessageContext;
import org.goface.rpc.RPC;
import org.goface.rpc.pipeline.ServicePipeLine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.goface.rpc.conf.ServiceConfigure;
import com.goface.rpc.conf.ServiceConfigureCenter;

/**
 * @author jm110
 */
public class RpcServerSideHandler extends ChannelHandlerAdapter {
    private Logger LOG = LoggerFactory.getLogger(RpcServerSideHandler.class);
    private ServicePipeLine servicePipeLine;

    public RpcServerSideHandler(ServicePipeLine servicePipeLine) {
        this.servicePipeLine = servicePipeLine;
    }

    private ServiceConfigure findServiceConfigure(String serviceName) {
        ServiceConfigureCenter serviceConfigureCenter = RPC.getServiceConfigureCenter();
        ServiceConfigure serviceConf = serviceConfigureCenter.getServiceConfigure(serviceName);
        return serviceConf;
    }

    private MessageContext createMessageContext(Message requestMsg, ServiceConfigure configure) {
        MessageContext requestCtx = MessageContext.createRequest();
        requestCtx.getProperties().putAll(configure.getProperties());
        requestCtx.setMessage(requestMsg);
        return requestCtx;
    }

    private Message createServerErrorMsg(Message requestMsg, String cause) {
        requestMsg.setCause("server error");
        requestMsg.setArgs(null);
        requestMsg.setOrders(null);
        return requestMsg;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        Message requestMsg = Message.class.cast(msg);
        try {
            ServiceConfigure configure = findServiceConfigure(requestMsg.getServiceName());
            if (configure == null) {
                String cause = "service not exist:" + requestMsg.getServiceName();
                LOG.error(cause);
                requestMsg.setCause(cause);
                ctx.channel().write(requestMsg);// 不走service pipe line,直接返回给客户端
                return;
            }
            MessageContext requestCtx = createMessageContext(requestMsg, configure);
            requestCtx.getProperties().put(MessageContext.CLIENT_CHANNEL, ctx.channel());
            servicePipeLine.fireReceiveRequest(requestCtx);

        } catch (Throwable th) {
            LOG.error("exception in receive request", th);
            Message reply = createServerErrorMsg(requestMsg, "server error");
            ctx.channel().write(reply);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // 无法确定是哪一次调用的异常，直接记录日志，上层调用自己超时结束
        LOG.error("exception caught pls check.", cause);
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object replyMsg, ChannelPromise promise) throws Exception {
        ctx.writeAndFlush(replyMsg, promise);

    }

}
